package com.bruce.tool.map.core.handler;

import java.util.List;

/**
 * 范围判断
 *
 * @author Bruce(刘正航)
 */
public class ScopeHandler {

    /**
     * @param lat     点的横坐标
     * @param lng     点的纵坐标
     * @param cycleLat 圆心横坐标
     * @param cycleLng 圆心纵坐标
     * @param radius 半径
     * @return 返回是否在圆形以内, 是true, 否false
     */
    public static boolean isPointInCycle(double lat, double lng, double cycleLat, double cycleLng, double radius) {
        double distance = DistanceHandler.getDistance(lat, lng, cycleLat, cycleLng);
        return radius - distance > 0;
    }

    /**
     * 计算点是否在多边形以内
     *
     * @param px        点的横坐标
     * @param py        点的纵坐标
     * @param polygonXa 多边形多个点的横坐标(与纵坐标顺序一致)
     * @param polygonYa 多边形多个点的纵坐标(与横坐标顺序一致)
     * @return 返回是否在多边形以内, 是true, 否false
     */
    public static boolean isPointInPolygon(double px, double py,
                                           List<Double> polygonXa, List<Double> polygonYa) {
        boolean isInside = false;
        double esp = 1e-9;
        int count = 0;
        double linePoint1x;
        double linePoint1y;
        double linePoint2x = 180;
        double linePoint2y;

        linePoint1x = px;
        linePoint1y = py;
        linePoint2y = py;

        for (int i = 0; i < polygonXa.size() - 1; i++) {
            double cx1 = polygonXa.get(i);
            double cy1 = polygonYa.get(i);
            double cx2 = polygonXa.get(i + 1);
            double cy2 = polygonYa.get(i + 1);
            if (isPointOnLine(linePoint1x, linePoint1y, cx1, cy1, cx2, cy2)) {
                return true;
            }
            if (Math.abs(cy2 - cy1) < esp) {
                continue;
            }

            if (isPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x,
                    linePoint2y)) {
                if (cy1 > cy2) {
                    count++;
                }
            } else if (isPointOnLine(cx2, cy2, linePoint1x, linePoint1y,
                    linePoint2x, linePoint2y)) {
                if (cy2 > cy1) {
                    count++;
                }
            } else if (isIntersect(cx1, cy1, cx2, cy2, linePoint1x,
                    linePoint1y, linePoint2x, linePoint2y)) {
                count++;
            }
        }
        if (count % 2 == 1) {
            isInside = true;
        }

        return isInside;
    }

    /**
     * 是否在多边形的边上
     */
    public static boolean isPointOnLine(double px0, double py0, double px1,
                                        double py1, double px2, double py2) {
        boolean flag = false;
        double esp = 1e-9;
        if ((Math.abs(multiply(px0, py0, px1, py1, px2, py2)) < esp)
                && ((px0 - px1) * (px0 - px2) <= 0)
                && ((py0 - py1) * (py0 - py2) <= 0)) {
            flag = true;
        }
        return flag;
    }

    /**
     * 两条线是否相交
     */
    public static boolean isIntersect(double px1, double py1, double px2, double py2,
                                      double px3, double py3, double px4, double py4) {
        boolean flag = false;
        double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
        if (d != 0) {
            double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3))
                    / d;
            double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1))
                    / d;
            if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1)) {
                flag = true;
            }
        }
        return flag;
    }

    public static double multiply(double px0, double py0, double px1, double py1,
                                  double px2, double py2) {
        return ((px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0));
    }
}
